package com.vhly.appspot.proxy;

import com.google.appengine.repackaged.com.google.common.util.Base64;
import com.google.appengine.repackaged.com.google.common.util.Base64DecoderException;
import com.vhly.appspot.util.StreamUtil;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Enumeration;

/**
 * Created by IntelliJ IDEA.
 * User: vhly
 * Date: 2009-11-3
 * Time: 10:59:48
 *
 * @author vhly[FR]
 */
public final class ProxyServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        work(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        work(request, response);
    }

    private static void work(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        long ct1 = System.currentTimeMillis();
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String queryString = request.getQueryString();
        String reloc = request.getParameter("reloc");
        String method = request.getMethod();
        String ua = request.getHeader("User-Agent");
        int stateCode = HttpServletResponse.SC_BAD_REQUEST;
        if (queryString != null) {
            boolean bok = false;
            int index = queryString.indexOf("url=");
            if (index > -1) {
                queryString = queryString.substring(index + "url=".length());
                bok = true;
            } else {
                index = queryString.indexOf("eu=");
                if (index > -1) {
                    try {
                        queryString = new String(Base64.decode(queryString.substring(index + "eu=".length())), "UTF-8");
                        bok = true;
                    } catch (Base64DecoderException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (bok) {
                System.out.println("queryString = " + queryString);
                URL url = null;
                HttpURLConnection httpConn = null;
                try {
                    if (!queryString.startsWith("http://") && !queryString.startsWith("https://")) {
                        queryString = "http://" + queryString;
                    }
                    url = new URL(queryString);
                    httpConn = (HttpURLConnection) url.openConnection();
                    if (reloc != null && reloc.equals("true")) {
                        httpConn.setInstanceFollowRedirects(false);
                    }
                    httpConn.setRequestMethod(method);
                    Enumeration names = request.getHeaderNames();
                    String n, v;
                    while (names.hasMoreElements()) {
                        n = (String) names.nextElement();
                        v = request.getHeader(n);
                        httpConn.setRequestProperty(n, v);
                    }
                    httpConn.setRequestProperty("Connection","close");
                    httpConn.setDoInput(true);
                    if (method.equals("POST")) {
                        httpConn.setDoOutput(true);
                    }
                    if (method.equals("POST")) {
                        OutputStream out = httpConn.getOutputStream();
                        ServletInputStream in = request.getInputStream();
                        // TODO 注意此处的数据流复制问题 性能
                        StreamUtil.writeStream(in, out);
                        out.close();
                    }
                    stateCode = httpConn.getResponseCode();
                    int i = 1;
                    try {
                        for (; i < 30; i++) {
                            n = httpConn.getHeaderFieldKey(i);
                            if (n == null) {
                                break;
                            }
                            v = httpConn.getHeaderField(i);
                            if (v != null) {
                                response.addHeader(n, v);
                            }
                        }
                    } catch (Exception e) {
                    }
                    response.setStatus(stateCode);
                    ServletOutputStream ou = response.getOutputStream();
                    InputStream in = httpConn.getInputStream();
                    // TODO 注意此处的数据流复制问题 性能
                    StreamUtil.writeStream(in, ou);
                    ou.flush();
                    long ctok = System.currentTimeMillis();
                    ctok -= ct1;
                    System.out.println(queryString + " ctok = " + ctok);

                } catch (SocketTimeoutException timeout) {
                    response.setStatus(HttpServletResponse.SC_REQUEST_TIMEOUT);
                }
                catch (Exception ex) {
                    System.out.println("ex.getMessage() = " + ex.getMessage());
                    response.setStatus(stateCode);
                } finally {
                    StreamUtil.close(httpConn);
                    httpConn = null;
                }
            } else {
                response.setStatus(stateCode);
            }
        } else {
            response.setStatus(stateCode);
        }
    }
}
